package com.shareyi.simpleserver.servlet.config;


import java.io.Serializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.shareyi.simpleserver.exception.SimpleServerException;
import com.shareyi.simpleserver.servlet.ServletContextListener;




public class ObjectFactory implements Serializable {

	private static final long serialVersionUID = -9086526874007371079L;

	
	
	private static final Log LOG = LogFactory.getLog(ObjectFactory.class);

    private transient ClassLoader ccl;

    public void setClassLoader(ClassLoader cl) {
        this.ccl = cl;
    }
    


    public ObjectFactory() {
    }




    /**
     * Allows for ObjectFactory implementations that support
     * Actions without no-arg constructors.
     *
     * @return true if no-arg constructor is required, false otherwise
     */
    public boolean isNoArgConstructorRequired() {
        return true;
    }

    /**
     * Utility method to obtain the class matched to className. Caches look ups so that subsequent
     * lookups will be faster.
     *
     * @param className The fully qualified name of the class to return
     * @return The class itself
     * @throws ClassNotFoundException
     */
    public Class getClassInstance(String className) throws ClassNotFoundException {
        if (ccl != null) {
            return ccl.loadClass(className);
        }

        return Class.forName(className);
    }

   

    /**
     * Build a generic Java object of the given type.
     *
     * @param clazz the type of Object to build
     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
     */
    public Object buildBean(Class clazz) throws Exception {
        return clazz.newInstance();
    }


    /**
     * Build a generic Java object of the given type.
     *
     * @param className the type of Object to build
     * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext}
     */
    public Object buildBean(String className) throws Exception {
        Class clazz = getClassInstance(className);
        Object obj = buildBean(clazz); 
        return obj;
    }

    /**
     * Builds an ServletContextListener from the ServletContextListenerConfig and the Map of
     * parameters from the listener reference. Implementations of this method
     * should ensure that the ServletContextListener is parameterized with both the
     * parameters from the ServletContextListener config and the listener ref Map (the
     * listener ref params take precedence), and that the ServletContextListener.init()
     * method is called on the ServletContextListener instance before it is returned.
     *
     * @param listenerConfig    the ServletContextListenerConfig from the configuration
     * @param listenerRefParams a Map of params provided in the ServletContextListener reference in the
     *                             Action mapping or ServletContextListenerStack definition
     */
    public ServletContextListener buildContextListener(ListenerBean listenerBean) throws SimpleServerException {
        String listenerClassName = listenerBean.getListenerClass();

        String message;
        Throwable cause;

        try {
            ServletContextListener listener = (ServletContextListener) buildBean(listenerClassName);
            return listener;
        } catch (InstantiationException e) {
            cause = e;
            message = "Unable to instantiate an instance of ServletContextListener class [" + listenerClassName + "].";
        } catch (IllegalAccessException e) {
            cause = e;
            message = "IllegalAccessException while attempting to instantiate an instance of ServletContextListener class [" + listenerClassName + "].";
        } catch (ClassCastException e) {
            cause = e;
            message = "Class [" + listenerClassName + "] does not implement com.shareyi.simpleserver.servlet.ServletContextListener";
        } catch (Exception e) {
            cause = e;
            message = "Caught Exception while registering ServletContextListener class " + listenerClassName;
        } catch (NoClassDefFoundError e) {
            cause = e;
            message = "Could not load class " + listenerClassName + ". Perhaps it exists but certain dependencies are not available?";
        }

        throw new SimpleServerException(message, cause);
    }


    

    
    
    
}
